`include "/home/lab/lab14/Computer_architecture/homwork/pc/src/pc.v"
`include "/home/lab/lab14/Computer_architecture/homwork/pc/src/tb_pc_interface.sv"
module tb_pc_top (
    
);
bit CLK;
    initial begin
        CLK = 1;
        repeat(150)begin
            #1 CLK = ~CLK;
        end
    end
    pc_if tb_pc_if(CLK);
    tb_pc tb_pc1(tb_pc_if);
    pc pc1(.CLK(CLK),.RESET(tb_pc_if.RESET),.LD(tb_pc_if.LD),.PCSEL(tb_pc_if.PCSEL)
    ,.OFFSET(tb_pc_if.OFFSET),.DIRECT(tb_pc_if.DIRECT),.PC_OUT(tb_pc_if.PC_OUT));
        //get randow value for the DUT(Generator)
    initial begin           
            tb_pc_if.RESET=1'b0;tb_pc_if.OFFSET=0;tb_pc_if.DIRECT=0;tb_pc_if.PCSEL=2'b01;
            #1
            tb_pc_if.RESET=1'b1;tb_pc_if.LD=1;tb_pc_if.PCSEL=2'b10;
            #1
        repeat(50) begin
                #2
                tb_pc_if.RESET=$random % 2;
                //tb_pc_if.LD = $random % 2 ;
                tb_pc_if.PCSEL={$random} % 4;
                tb_pc_if.OFFSET=$random % 255;
                tb_pc_if.DIRECT=$random % 255;
            
            end
        end     
        initial begin
        #100
        $display("The Test finish!!!");
        $stop;
        end
        initial begin
        $dumpfile("tb_pc_top.vcd");
        $dumpvars(0,tb_pc_top);
    end
 
endmodule

module tb_pc (
    pc_if tb_pc_if
);
    //logic [15:0] PC_OUT_expect,D_expect;

    always @(posedge tb_pc_if.CLK) begin
        if (tb_pc_if.RESET==1'b1) begin
                tb_pc_if.PC_OUT_expect <= {16{1'b0}};
            end 
        else if (tb_pc_if.LD==1'b0) begin
                tb_pc_if.PC_OUT_expect <= tb_pc_if.PC_OUT_expect;
            end 
        else begin 
                tb_pc_if.PC_OUT_expect = tb_pc_if.D_expect;
            end
            case (tb_pc_if.PCSEL)
                2'b00: tb_pc_if.D_expect <= tb_pc_if.PC_OUT_expect + 1;
                2'b01: tb_pc_if.D_expect <= tb_pc_if.OFFSET;
                2'b10: tb_pc_if.D_expect <= tb_pc_if.DIRECT;
                2'b11: tb_pc_if.D_expect <= {16{1'bz}};
            default: ;
            endcase  
    end      
task reference(
        input [15:0] PC_OUT_expect,
        input [15:0] tb_pc_if_PC_OUT
        //input tb_pc_if_CLK
    );
	begin
//	$display("TIME is %t The PC_OUT is %h and the PC_OUT_expect is %h",$time,tb_pc_if.PC_OUT,tb_pc_if.PC_OUT_expect);
	end
        if (bit'(tb_pc_if.PC_OUT_expect) == bit'(tb_pc_if.PC_OUT)) begin
            $display("PASSED !!!");
        end 
	else begin
            $display("Failed!!! Time is %t,The PC_OUT_expect is %d,and the PC_OUT is %d",$time,tb_pc_if.PC_OUT_expect,tb_pc_if.PC_OUT);
        end         
    endtask    
    always @(tb_pc_if.CLK) begin
            reference(tb_pc_if.PC_OUT_expect,tb_pc_if.PC_OUT);
            
            end
    
//       initial begin
//       repeat(50) begin
//        reference(PC_OUT_expect,tb_pc_if.PC_OUT);
//          end
//           $stop;
//          end
endmodule